#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <signal.h>


#include "global.h"
#include "constantes.h"
#include "listas.h"
#include "sockets.h"
#include "configuracion.h"
#include "NIPC.h"


#define	STDIN 1


struct DiscoConocido * BuscarDiscoPorNombre(char * sNombreDiscoABuscar);
void * ConsolaEsperaNuevosDiscos (void * pSocketParaArray);
void configToCHS();
chs getCHS(); 


extern ListConfig * listaConfig;
int main ()
{	

   
    InfoIPC rInfoIPC;;
    struct sockaddr_in Str_sockaddr_in_paraAcept;
    int iAddress_size= sizeof(struct sockaddr_in);
    fd_set set_socketsHiloPrincipal;			/**lista de sockets que se van a hacer que se active el select del hilo principal cuando reciban algo**/
    struct Pedido_PutSectores *pPedidoPut;
    int iRecibidos;
    int *pSector1;
    int *pSector2;
    char *BufAux;
    char sDescriptorID[20];
    char IDdescriptor_dePedido[20];
    char PayloadDescriptor;
    char sSocketPorElCualResponder[50];
    char sNombreDisco[100];
    int iMayorSocket;
    int iSocketConectado;
    int *pPosicionVec;
    char sBuffer[1500];
    char sAux[20];
    char sSocketAux[20];
    int *pSocketArrayParaConsola;  		
    int *pSocketAux;			
    int iSocketEscuchaPedidosSincro;	
    int iSocket_temporal;		
    int iSector1, iSector2;
    struct DiscoConocido * pAuxDisco;
    pthread_t ID_HiloDisco;
    pthread_t ID_HiloParaConsolaEsperarConexionDiscos;
    int ret,i;
    struct sockaddr_in sin;
    int numeroPedido;
    struct DiscoConocido * pDiscoAsignado;
    pid_t child;
    
    /*****INICIALIZACION DE VARIABLES******/
    Estado= FUERA_DE_SERVICIO;
    SubEstado = INCOMPLETO;
    ListaDiscos = NULL;
    ListaDiscos_Ult = NULL;
    ListaPedidos_Put = NULL;
    ListaPedidos_Put_Ult = NULL;
    ArrayCompleto = FALSO;
    /************************************/


	
	listaConfig = NULL;
   cargarConfig();
	
   iCantidadDiscosDeArchivoConfig=atoi(obtenerValor("minimoDiscos"));
   
   pDiscosDeArchivoConfig = malloc( sizeof(struct DiscoDeArchivoConfig) * iCantidadDiscosDeArchivoConfig );
      
   for(i=0 ; i< iCantidadDiscosDeArchivoConfig ; i++)
	{	
      strcpy(pDiscosDeArchivoConfig[i].sNombre,obtenerValor("nombreDiscos"));
      pDiscosDeArchivoConfig[i].sNombre[ strlen ( pDiscosDeArchivoConfig[i].sNombre ) - 1 ] = '\0';
      pDiscosDeArchivoConfig[i].Conectado = FALSO;
	}
   
	configToCHS();	
		
	printf("glChs.cilindros %i \n",glChs.cilindros);
	printf("glChs.cabezal %i \n",glChs.cabezal);
	printf("glChs.sectores %i \n",glChs.sectores);
	
	pSocketArrayParaConsola =malloc(sizeof(int));
   pSocketAux = malloc(sizeof(int));						
   
   CrearYConectarDosSockets(pSocketArrayParaConsola,pSocketAux,obtenerValor("ipLocal"));
    
	printf("socket1: %i \n",*pSocketArrayParaConsola);
	printf("socket2: %i \n",*pSocketAux);	
 

	ret=pthread_create(&ID_HiloParaConsolaEsperarConexionDiscos,NULL,(void *)ConsolaEsperaNuevosDiscos ,(void *)pSocketAux); 

   /*---------------------------------------------------------------------------------------------------------------------*/
   
	recibirIPC(*pSocketArrayParaConsola, &rInfoIPC);
	
   
   sin.sin_family = AF_INET;         
   sin.sin_port = htons(atoi(obtenerValor("puertoLocal"))+1);  
   sin.sin_addr.s_addr =INADDR_ANY; 
	
   iSocketEscuchaPedidosSincro = crearSocket(AF_INET);

   if(bind(iSocketEscuchaPedidosSincro, (struct sockaddr*)&sin, sizeof(sin)) == -1){
      close(iSocketEscuchaPedidosSincro);
      return ERRORBIND;
   }
    
   escuchar(iSocketEscuchaPedidosSincro,10);
    
    
 
   /* fork y exec de proceso pedido
	
   if((child=fork())==-1){
		perror("fork");
		exit(EXIT_FAILURE);    
   }
    else if (child==0){
		execv("./pedido",NULL);	
   }
	
   */
    

	while(1)
   {			
		FD_ZERO(&set_socketsHiloPrincipal);
		FD_SET(*pSocketArrayParaConsola, &set_socketsHiloPrincipal);
		if(*pSocketArrayParaConsola > iMayorSocket)
			iMayorSocket = *pSocketArrayParaConsola;
		
		FD_SET(iSocketEscuchaPedidosSincro, &set_socketsHiloPrincipal);
		if(iSocketEscuchaPedidosSincro > iMayorSocket)
			iMayorSocket = iSocketEscuchaPedidosSincro;
      
		pAuxDisco = ListaDiscos;
		while(pAuxDisco != NULL)
		{
			FD_SET(pAuxDisco->iSocketArrayParaHDA , &set_socketsHiloPrincipal);	
			if(pAuxDisco->iSocketArrayParaHDA > iMayorSocket)
				iMayorSocket = pAuxDisco->iSocketArrayParaHDA;
			pAuxDisco = pAuxDisco->Sgt;
		}
		  

       
		select(iMayorSocket + 1,&set_socketsHiloPrincipal, NULL, NULL, NULL);
       
		
       
       // /*RESPUESTA DE ALGUN HILO DE DISCO*/
		// pAuxDisco = ListaDiscos;
		// while(pAuxDisco != NULL)
		// {
			// if( FD_ISSET(pAuxDisco->iSocketArrayParaHDA , &set_socketsHiloPrincipal ) > 0 )
				// break;
			// pAuxDisco = pAuxDisco->Sgt;
		// }
      // if(pAuxDisco != NULL)
		// {	
         // memset(sBuffer, '\0', sizeof(sBuffer) );												
         // /*rInfoIPC.payLoadDescriptor = NADA;*/
         
         // recibirIPC(pAuxDisco->iSocketArrayParaHDA,&rInfoIPC); /*IDdescriptor_dePedido*/
         // strcpy(IDdescriptor_dePedido,rInfoIPC.payload);
         
         // if(rInfoIPC.payLoadDescriptor == TERMINAR_CONEXION)
         // {
            // printf(" EL Array se encuentra corrupto, por ello se desconecta\r\n");
            // exit(1);
         // }
         
         // /*if(rInfoIPC.payLoadDescriptor == NADA)
         // {
            // cerrarSocket(pAuxDisco->iSocketArrayParaHDA);
            // SacarDeLista_DA(&pAuxDisco);
            // free(pAuxDisco);
            // printf("Disco desconectado");
            // continue;
         // }
         // */
         
         // recibirIPC(pAuxDisco->iSocketArrayParaHDA,&rInfoIPC); /*Recibo sSocketPorElCualResponder*/
         // strcpy(sSocketPorElCualResponder,rInfoIPC.payload);
         // recibirIPC(pAuxDisco->iSocketArrayParaHDA,&rInfoIPC); /*Recibo sBuffer*/
         // strcpy(sBuffer,rInfoIPC.payload);
    
         // switch(rInfoIPC.payLoadDescriptor)
         // {
            // case RTA_PUT_SECTORES:
               
              // printf("Recibi:%s \n",rInfoIPC.payload);
              // break;
 
            // case RTA_GET_SECTORES:
            
              // printf("Recibi:%s \n",rInfoIPC.payload);	
              // break;
            
            // default:
               // break;
               
         // }		
		// }

      
		//CONSOLA
		if( FD_ISSET(*pSocketArrayParaConsola, &set_socketsHiloPrincipal ) > 0 )
		{
			iRecibidos = recibirIPC(*pSocketArrayParaConsola,&rInfoIPC);
			
			printf(" ACA ESTOY \n");
			
			if( (Estado == FUERA_DE_SERVICIO) )
			{
				printf("Proximamente\n");
				continue;
			}	

			switch (rInfoIPC.payLoadDescriptor) 
			{
				case PUT_SECTORES:
               printf("Proximamente1\n");
               break;

				case GETCHS:
               printf("Proximamente2\n"); 
               break;

				case GET_SECTORES:
               printf("Proximamente3\n");
               break;

            case DA_CONECTADO_CORRECTAMENTE:
              printf("DA_CONECTADO_CORRECTAMENTE\n");
              break;
			}

		}

      
      // //PEDIDOS DE SINCRONIZACION
		// if( FD_ISSET(iSocketEscuchaPedidosSincro, &set_socketsHiloPrincipal ) > 0 )
		// {
			// printf("Pedidos por sincro\n");
			// iSocket_temporal = ( int ) accept ( iSocketEscuchaPedidosSincro , ( struct sockaddr * ) &Str_sockaddr_in_paraAcept , &iAddress_size );
			// recibirIPC(iSocket_temporal,&rInfoIPC);;
			// if( (Estado == FUERA_DE_SERVICIO)  )
				// continue;
		
			// if(PayloadDescriptor == GET_SECTORES)
			// {			
				// strcpy(sNombreDisco, sBuffer);
				// pAuxDisco = BuscarDiscoPorNombre(sNombreDisco);		

				// if(pAuxDisco == NULL)
					// printf("No existe\n");
				// else
					// printf("Pedido de getsectores\n");
			// }

		// }

	}

   free(pSocketArrayParaConsola);
   free(pSocketAux);
   return 0;

}


void configToCHS()
{
	/* No recibe parámetros y devuelve tres enteros correspondientes a la información física obtenida de archivo de configuración. */
	char* ntok;
	char* chsAux;
	chs resultadoChs;
	
	chsAux = (char*)malloc(strlen(obtenerValor("CHS"))+1);
	strcpy(chsAux,obtenerValor("CHS"));

	resultadoChs.cilindros = atoi(strtok(chsAux,","));
	resultadoChs.cabezal = atoi(strtok(NULL,","));
	resultadoChs.sectores = atoi(strtok(NULL,","));
	
	glChs = resultadoChs;
   
   free(chsAux);
}

chs getCHS()
{
	return glChs;
}

